package bookstore.manager.impl;

import bookstore.bound.auth.LoginForm;
import bookstore.manager.AuthManager;
import bookstore.model.User;
import bookstore.repository.UserRepository;
import bookstore.utils.AuthenticateException;
import bookstore.utils.CryptoUtils;
import bookstore.utils.SessionUtils;
import bookstore.utils.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

@Service
public class AuthManagerImpl implements AuthManager {
    @Autowired
    protected UserRepository userRepository;

    protected SessionUtils sessionUtils = new SessionUtils();
    protected CryptoUtils cryptoUtils = new CryptoUtils();

    @Override
    public Map authCheck(HttpSession session) {
        Optional<UserInfo> info = sessionUtils.getProfile(session);
        Optional<Long> uid = info.map(UserInfo::getUserId);
        uid.flatMap(userRepository::findById).ifPresent(user -> sessionUtils.setProfile(session, user));


        Map<String, Object> rsp = new HashMap<>();
        rsp.put("success", uid.isPresent());
        sessionUtils.getProfile(session).ifPresent(userInfo -> rsp.put("profile", userInfo));

        return rsp;
    }


    @Override
    public Map login(HttpSession session, LoginForm form) {
        Optional<User> opt = userRepository.findByEmail(form.getEmail());

        opt.ifPresent(user -> {
            if (cryptoUtils.check(user.getUserid(), form.getPass(), user.getPwd())) {
                sessionUtils.setProfile(session, user);
            }
        });

        Map rsp = authCheck(session);
        rsp.put("enroll", opt.isPresent());

        return rsp;
    }

    @Override
    public boolean requireLogin(HttpSession session) throws AuthenticateException {
        if (sessionUtils.getProfile(session).map(UserInfo::getUserId).isPresent()) {
            return true;
        } else {
            throw new AuthenticateException(AuthenticateException.AuthType.LOGIN);
        }
    }

    @Override
    public boolean requireAdmin(HttpSession session) throws AuthenticateException {
        requireLogin(session);
        if (sessionUtils.getProfile(session).map(UserInfo::isAdmin).get()) {
            return true;
        } else {
            throw new AuthenticateException(AuthenticateException.AuthType.ADMIN);
        }
    }
}
